package ru.gerunn.test.jndi;

import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Hashtable;

import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.NoInitialContextException;
import javax.naming.spi.InitialContextFactory;
import javax.naming.spi.InitialContextFactoryBuilder;

public class CloseSafeMemoryContextFactoryBuilder implements InitialContextFactoryBuilder {

	public InitialContextFactory createInitialContextFactory(Hashtable<?, ?> env) throws NamingException {
		String requestedFactory = null;
		if (env != null) {
			requestedFactory = (String) env.get(Context.INITIAL_CONTEXT_FACTORY);
		}

		if (requestedFactory != null) {
			return simulateBuilderlessNamingManager(requestedFactory);
		}

		return new CloseSafeMemoryContextFactory();
	}

	private InitialContextFactory simulateBuilderlessNamingManager(String requestedFactory) throws NoInitialContextException {
		try {
			ClassLoader cl = getContextClassLoader();
			Class<?> requestedClass = Class.forName(requestedFactory, true, cl);
			return (InitialContextFactory) requestedClass.newInstance();
		} catch (Exception e) {
			NoInitialContextException ne = new NoInitialContextException("");
			ne.setRootCause(e);
			throw ne;
		}
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	private ClassLoader getContextClassLoader() {
		return (ClassLoader) AccessController.doPrivileged(new PrivilegedAction() {
			public Object run() {
				return Thread.currentThread().getContextClassLoader();
			}
		});
	}

}
